#include "stdafx.h"
#include "UtilConvert.h"

CStringA Util::Convert::Utf8FromWS(const wchar_t * str, int len)
{
	return Utf8FromWSLimit(0x7fffffff, str, len);
}

CStringA Util::Convert::Utf8FromWSLimit(int limit, const wchar_t * str, int len)
{
	if(len<0) len = _tcslen(str);
	CStringA sr;
	if (limit <= 0 || len == 0)
	{
		return sr;
	}
	int utf8len = 0;
	for (int i=0; i<len; ++i)
	{
		int marki = i;
		unsigned short us = str[i];
		if (us == 0)
		{
			utf8len += 2;
		}
		else if (us <= 0x7f)
		{
			utf8len += 1;
		}
		else if (us <= 0x7ff)
		{
			utf8len += 2;
		}
		else if (0xd800 <= us && us <= 0xdbff && i+1<len)
		{
			unsigned short ul = str[i+1];
			if (0xdc00 <= ul && ul <= 0xdfff)
			{
				++i;
				utf8len += 4;
			}
			else
			{
				utf8len += 3;
			}
		}
		else
		{
			utf8len += 3;
		}
		if (utf8len > limit)
		{
			len = marki;
			break;
		}
	}

	PBYTE pc = (PBYTE)sr.GetBuffer(utf8len+1);
	for (int i=0; i<len; ++i)
	{
		unsigned short us = str[i];
		if (us == 0)
		{
			*pc ++ = 0xc0;
			*pc ++ = 0x80;
		}
		else if (us <= 0x7f)
		{
			*pc ++ = (char)us;
		}
		else if (us <= 0x7ff)
		{
			*pc ++ = 0xc0 | (us >> 6);
			*pc ++ = 0x80 | (us & 0x3f);
		}
		else if(0xd800 <= us && us <= 0xdbff && i+1<len)
		{
			unsigned short ul = str[i+1];
			if (0xdc00 <= ul && ul <= 0xdfff)
			{
				++i;
				UINT bc = (us-0xD800)*0x400 + (ul-0xDC00) + 0x10000;
				*pc ++ = (BYTE)(0xf0 | ((bc >> 18) & 0x07));
				*pc ++ = (BYTE)(0x80 | ((bc >> 12) & 0x3f));
				*pc ++ = (BYTE)(0x80 | ((bc >>  6) & 0x3f));
				*pc ++ = (BYTE)(0x80 | ((bc      ) & 0x3f));
			}
			else
			{
				*pc ++ = (BYTE) (0xe0 | ((us >> 12) & 0x0f));
				*pc ++ = (BYTE) (0x80 | ((us >>  6) & 0x3f));
				*pc ++ = (BYTE) (0x80 | ((us      ) & 0x3f));
			}
		}
		else
		{
			*pc ++ = (BYTE) (0xe0 | ((us >> 12) & 0x0f));
			*pc ++ = (BYTE) (0x80 | ((us >>  6) & 0x3f));
			*pc ++ = (BYTE) (0x80 | ((us      ) & 0x3f));
		}
	}
	* pc++ = 0;
	sr.ReleaseBuffer();
	return sr;
}

CString Util::Convert::Utf8ToWS(CStringA strTempA)
{
	return Util::Convert::Utf8ToWS(strTempA.GetBuffer(), strTempA.GetLength());
}

CString Util::Convert::Utf8ToWS(const char * str, int len)
{
	CString sw;
	if (str == 0) return sw;
	if (len <  0) len = (int)strlen(str);
	if (len == 0) return sw;

	int nLength = MultiByteToWideChar(CP_UTF8,0,str,len,0,0);
	MultiByteToWideChar(CP_UTF8, 0,str,len,sw.GetBuffer(nLength+1),nLength);
	sw.ReleaseBuffer(nLength);

	return sw;
}


CStringA Util::Convert::IntToStringA(int iValue)
{
	CStringA str;
	str.Format("%d", iValue);
	return str;
}
CStringA Util::Convert::DWordToStringA(DWORD dwValue)
{
	CStringA str;
	str.Format("%lu", dwValue);
	return str;
}
CStringA Util::Convert::Int64ToStringA(__int64 i64Value)
{
	CStringA str;
	str.Format("%I64d", i64Value);
	return str;
}
CStringA Util::Convert::UnsignedInt64ToStringA(unsigned __int64 ui64Value)
{
	CStringA str;
	str.Format("%I64u", ui64Value);
	return str;
}

CStringW Util::Convert::IntToStringW(int iValue)
{
	CStringW str;
	str.Format(L"%d", iValue);
	return str;
}
CStringW Util::Convert::DWordToStringW(DWORD dwValue)
{
	CStringW str;
	str.Format(L"%lu", dwValue);
	return str;
}
CStringW Util::Convert::Int64ToStringW(__int64 iValue)
{
	CStringW str;
	str.Format(L"%I64d", iValue);
	return str;
}
CStringW Util::Convert::UnsignedInt64ToStringW(unsigned __int64 iValue)
{
	CStringW str;
	str.Format(L"%I64u", iValue);
	return str;
}

bool Util::Convert::StringToIntA(const char* strValue, int & iValue)
{
	iValue = 0;
	bool br = true;
	if (!strValue || !*strValue)
	{
		return false;
	}
	while (isspace((int)*strValue))
	{
		strValue ++;
	}
	if (*strValue == '+' || *strValue == '-')
	{
		br = (*strValue++ == '+');
	}
	bool bOK = true;
	if (strValue[0] == '0' && (strValue[1]|0x20)=='x')
	{
		strValue += 2;
		for (;;)
		{
			TCHAR ch = *strValue;
			int iValue2 = 0;
			if (ch >= '0' && ch <= '9')	iValue2 = iValue*16 + ch -'0';
			else if (ch>='a' && ch<='f') iValue2 = iValue*16 + ch -'a'+10;
			else if (ch>='A' && ch<='F') iValue2 = iValue*16 + ch -'A'+10;
			else break;
			if (iValue2 < 0 || iValue >= 134217728)	bOK = false;
			iValue = iValue2;
			++strValue;
		}
	}
	else
	{
		while (*strValue >= '0' && *strValue <= '9')
		{
			int iValue2 = iValue * 10 + *strValue++ -'0';
			if (iValue2 < 0 || iValue > 214748364) bOK = false;
			iValue = iValue2;
		}
	}
	if (!br) iValue = -iValue;
	while (*strValue && isspace((BYTE)*strValue)) ++strValue;
	return bOK && strValue[0] == 0;
}
bool Util::Convert::StringToDWordA(const char* strValue, DWORD & dwValue)
{
	dwValue = 0;
	if (!strValue || !*strValue)
	{
		return false;
	}
	while (isspace((int)*strValue))
	{
		strValue ++;
	}
	if (*strValue == '+')
	{
		strValue ++;
	}
	bool bOK = true;
	if (strValue[0] == '0' && (strValue[1]|0x20)=='x')
	{
		strValue += 2;
		for (;;)
		{
			TCHAR ch = *strValue;
			DWORD dwValue2 = 0;
			if (ch >= '0' && ch <= '9')	dwValue2 = dwValue*16 + ch -'0';
			else if (ch>='a' && ch<='f') dwValue2 = dwValue*16 + ch -'a'+10;
			else if (ch>='A' && ch<='F') dwValue2 = dwValue*16 + ch -'A'+10;
			else break;
			if (dwValue2 < dwValue || dwValue >= 268435456) bOK = false;
			dwValue = dwValue2;
			++strValue;
		}
	}
	else
	{
		while (*strValue >= '0' && *strValue <= '9')
		{
			DWORD dwValue2 = dwValue * 10 + *strValue++ -'0';
			if (dwValue2 < dwValue || dwValue > 429496729) bOK = false;
			dwValue = dwValue2;
		}
	}
	while (*strValue && isspace((BYTE)*strValue)) ++strValue;
	return bOK && strValue[0] == 0;
}
bool Util::Convert::StringToInt64A(const char* strValue, __int64 & i64Value)
{
	i64Value = 0;
	bool br = true;
	if (!strValue || !*strValue)
	{
		return false;
	}
	while (isspace((int)*strValue))
	{
		strValue ++;
	}
	if (*strValue == '+' || *strValue == '-')
	{
		br = (*strValue++ == '+');
	}
	bool bOK = true;
	if (strValue[0] == '0' && (strValue[1]|0x20)=='x')
	{
		strValue += 2;
		for (;;)
		{
			TCHAR ch = *strValue;
			__int64 i64Value2 = 0;
			if (ch >= '0' && ch <= '9')	i64Value2 = i64Value*16 + ch -'0';
			else if (ch>='a' && ch<='f') i64Value2 = i64Value*16 + ch -'a'+10;
			else if (ch>='A' && ch<='F') i64Value2 = i64Value*16 + ch -'A'+10;
			else break;
			if (i64Value2 < 0 || i64Value >= 576460752303423488ULL) bOK = false;
			i64Value = i64Value2;
			++strValue;
		}
	}
	else
	{
		while (*strValue >= '0' && *strValue <= '9')
		{
			__int64 i64Value2 = i64Value * 10 + *strValue++ -'0';
			if (i64Value2 < 0 || i64Value > 922337203685477580ULL) bOK = false;

			i64Value = i64Value2;
		}
	}
	if (!br) i64Value = -i64Value;
	while (*strValue && isspace((BYTE)*strValue)) ++strValue;
	return bOK && strValue[0] == 0;
}
bool Util::Convert::StringToUnsignedInt64A(const char* strValue, unsigned __int64 & ui64Value)
{
	ui64Value = 0;
	if (!strValue || !*strValue)
	{
		return false;
	}
	while (isspace((int)*strValue))
	{
		strValue ++;
	}
	if (*strValue == '+')
	{
		strValue ++;
	}
	bool bOK = true;
	if (strValue[0] == '0' && (strValue[1]|0x20)=='x')
	{
		strValue += 2;
		for (;;)
		{
			TCHAR ch = *strValue;
			unsigned __int64 ui64Value2 = 0;
			if (ch >= '0' && ch <= '9')	ui64Value2 = ui64Value*16 + ch -'0';
			else if (ch>='a' && ch<='f') ui64Value2 = ui64Value*16 + ch -'a'+10;
			else if (ch>='A' && ch<='F') ui64Value2 = ui64Value*16 + ch -'A'+10;
			else break;
			if (ui64Value2 < ui64Value || ui64Value >= 1152921504606846976ULL) bOK = false;
			ui64Value = ui64Value2;
			++strValue;
		}
	}
	else
	{
		while (*strValue >= '0' && *strValue <= '9')
		{
			unsigned __int64 ui64Value2 = ui64Value * 10 + *strValue++ -'0';
			if (ui64Value2 < ui64Value || ui64Value > 1844674407370955161ULL) bOK = false;
			ui64Value = ui64Value2;
		}
	}
	while (*strValue && isspace((BYTE)*strValue)) ++strValue;
	return bOK && strValue[0] == 0;
}

bool Util::Convert::StringToIntW(const wchar_t* strValue, int & iValue)
{
	iValue = 0;
	bool br = true;
	if (!strValue || !*strValue)
	{
		return false;
	}
	while (iswspace(*strValue))
	{
		strValue ++;
	}
	if (*strValue == '+' || *strValue == '-')
	{
		br = (*strValue++ == '+');
	}
	bool bOK = true;
	if (strValue[0] == '0' && (strValue[1]|0x20)=='x')
	{
		strValue += 2;
		for (;;)
		{
			TCHAR ch = *strValue;
			int iValue2 = 0;
			if (ch >= '0' && ch <= '9')	iValue2 = iValue*16 + ch -'0';
			else if (ch>='a' && ch<='f') iValue2 = iValue*16 + ch -'a'+10;
			else if (ch>='A' && ch<='F') iValue2 = iValue*16 + ch -'A'+10;
			else break;
			if (iValue2 < 0 || iValue >= 134217728)	bOK = false;
			iValue = iValue2;
			++strValue;
		}
	}
	else
	{
		while (*strValue >= '0' && *strValue <= '9')
		{
			int iValue2 = iValue * 10 + *strValue++ -'0';
			if (iValue2 < 0 || iValue > 214748364) bOK = false;
			iValue = iValue2;
		}
	}
	if (!br) iValue = -iValue;
	while (*strValue && isspace((BYTE)*strValue)) ++strValue;
	return bOK && strValue[0] == 0;
}

bool Util::Convert::StringToDWordW(const wchar_t* strValue, DWORD & dwValue)
{
	dwValue = 0;
	if (!strValue || !*strValue)
	{
		return false;
	}
	while (iswspace(*strValue))
	{
		strValue ++;
	}
	if (*strValue == '+')
	{
		strValue ++;
	}
	bool bOK = true;
	if (strValue[0] == '0' && (strValue[1]|0x20)=='x')
	{
		strValue += 2;
		for (;;)
		{
			TCHAR ch = *strValue;
			DWORD dwValue2 = 0;
			if (ch >= '0' && ch <= '9')	dwValue2 = dwValue*16 + ch -'0';
			else if (ch>='a' && ch<='f') dwValue2 = dwValue*16 + ch -'a'+10;
			else if (ch>='A' && ch<='F') dwValue2 = dwValue*16 + ch -'A'+10;
			else break;
			if (dwValue2 < dwValue || dwValue >= 268435456) bOK = false;
			dwValue = dwValue2;
			++strValue;
		}
	}
	else
	{
		while (*strValue >= '0' && *strValue <= '9')
		{
			DWORD dwValue2 = dwValue * 10 + *strValue++ -'0';
			if (dwValue2 < dwValue || dwValue > 429496729) bOK = false;
			dwValue = dwValue2;
		}
	}
	while (*strValue && isspace((BYTE)*strValue)) ++strValue;
	return bOK && strValue[0] == 0;
}
bool Util::Convert::StringToInt64W(const wchar_t* strValue, __int64 & i64Value)
{
	i64Value = 0;
	bool br = true;
	if (!strValue || !*strValue)
	{
		return false;
	}
	while (iswspace(*strValue))
	{
		strValue ++;
	}
	if (*strValue == '+' || *strValue == '-')
	{
		br = (*strValue++ == '+');
	}
	bool bOK = true;
	if (strValue[0] == '0' && (strValue[1]|0x20)=='x')
	{
		strValue += 2;
		for (;;)
		{
			TCHAR ch = *strValue;
			__int64 i64Value2 = 0; 
			if (ch >= '0' && ch <= '9')	i64Value2 = i64Value*16 + ch -'0';
			else if (ch>='a' && ch<='f') i64Value2 = i64Value*16 + ch -'a'+10;
			else if (ch>='A' && ch<='F') i64Value2 = i64Value*16 + ch -'A'+10;
			else break;
			if (i64Value2 < 0 || i64Value >= 1844674407370955161ULL) bOK = false;
			i64Value = i64Value2;
			++strValue;
		}
	}
	else
	{
		while (*strValue >= '0' && *strValue <= '9')
		{
			__int64 i64Value2 = i64Value * 10 + *strValue++ -'0';
			if (i64Value2 < 0 || i64Value > 576460752303423488ULL) bOK = false;
			i64Value = i64Value2;
		}
	}
	if (!br) i64Value = -i64Value;
	while (*strValue && isspace((BYTE)*strValue)) ++strValue;
	return bOK && strValue[0] == 0;
}
bool Util::Convert::StringToUnsignedInt64W(const wchar_t* strValue, unsigned __int64 & ui64Value)
{
	ui64Value = 0;
	if (!strValue || !*strValue)
	{
		return false;
	}
	while (iswspace(*strValue))
	{
		strValue ++;
	}
	if (*strValue == '+')
	{
		strValue ++;
	}
	bool bOK = true;
	if (strValue[0] == '0' && (strValue[1]|0x20)=='x')
	{
		strValue += 2;
		for (;;)
		{
			TCHAR ch = *strValue;
			unsigned __int64 ui64Value2 = 0;
			if (ch >= '0' && ch <= '9')	ui64Value2 = ui64Value*16 + ch -'0';
			else if (ch>='a' && ch<='f') ui64Value2 = ui64Value*16 + ch -'a'+10;
			else if (ch>='A' && ch<='F') ui64Value2 = ui64Value*16 + ch -'A'+10;
			else break;
			if (ui64Value2 < ui64Value || ui64Value >= 1152921504606846976ULL) bOK = false;
			ui64Value = ui64Value2;
			++strValue;
		}
	}
	else
	{
		while (*strValue >= '0' && *strValue <= '9')
		{
			unsigned __int64 ui64Value2 = ui64Value * 10 + *strValue++ -'0';
			if (ui64Value2 < ui64Value || ui64Value > 1844674407370955161ULL) bOK = false;
			ui64Value = ui64Value2;
		}
	}
	while (*strValue && isspace((BYTE)*strValue)) ++strValue;
	return bOK && strValue[0] == 0;
}
